package com.springboot.frame.excel.util;

import lombok.extern.slf4j.Slf4j;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author madman
 */
@Slf4j
public class ReflectionKit {

  private ReflectionKit() {
  }

  /**
   * 通过反射获值
   *
   * @param object 对象
   * @param method 方法
   * @return 值
   */
  public static Object getRefValue(Object object, Method method) {
    try {
      return method.invoke(object);
    } catch (ReflectiveOperationException e) {
      log.warn("获取数据失败，返回null", method.getName(), e);
      return null;
    }
  }

  /**
   * 通过反射设值
   *
   * @param object 对象
   * @param method 方法
   * @param args 方法参数
   * @throws ReflectiveOperationException 反射操作异常
   */
  public static void setRefValue(Object object, Method method, Object... args)
      throws ReflectiveOperationException {
    method.invoke(object, args);
  }

  /**
   * 获取对应的字段及其对应的Getter方法
   *
   * @param clazz Class对象
   * @return 该Class对象对应的字段及其对应的Getter方法
   * @throws IntrospectionException 内省异常
   */
  public static Map<Field, Method> fieldAndGetterMethod(Class clazz) throws IntrospectionException {
    Map<Field, Method> map = new LinkedHashMap<>();
    BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
    PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
    for (Field field : clazz.getDeclaredFields()) {
      for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
        if (propertyDescriptor.getName().equals(field.getName())) {
          map.put(field, propertyDescriptor.getReadMethod());
        }
      }
    }
    return map;
  }

  /**
   * 获取对应的字段及其对应的Setter方法
   *
   * @param clazz Class对象
   * @return 该Class对象对应的字段及其对应的Setter方法
   * @throws IntrospectionException 内省异常
   */
  public static Map<Field, Method> fieldAndSetterMethod(Class clazz) throws IntrospectionException {
    Map<Field, Method> map = new LinkedHashMap<>();
    BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
    PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
    for (Field field : clazz.getDeclaredFields()) {
      for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
        if (propertyDescriptor.getName().equals(field.getName())) {
          map.put(field, propertyDescriptor.getWriteMethod());
        }
      }
    }
    return map;
  }

}
